<!DOCTYPE html>

<!--[if lt IE 7 ]><html class="ie ie6" lang="en"> <![endif]-->
<!--[if IE 7 ]><html class="ie ie7" lang="en"> <![endif]-->
<!--[if IE 8 ]><html class="ie ie8" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--><html lang="en"> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <title>Functions / Learn Vimscript the Hard Way</title>
        <meta name="description" content="">
        <meta name="author" content="Steve Losh">
        <!--[if lt IE 9]>
            <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->

        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

        <link href="/static/styles/skeleton/base.css" rel="stylesheet" type="text/css" />
        <link href="/static/styles/skeleton/skeleton.css" rel="stylesheet" type="text/css" />
        <link href="/static/styles/skeleton/layout.css" rel="stylesheet" type="text/css" />

        <link href="/static/styles/tango.css" rel="stylesheet" type="text/css" />
        <link href="/static/styles/style.less" rel="stylesheet/less" type="text/css" />

        <script type="text/javascript" src="/static/scripts/less.js"></script>
    </head>

    <body class="">
        <div class="container">
            <header class="sixteen columns">
                <h1><a href="/">Learn Vimscript the Hard Way</a></h1>
            </header>

            
    <section class="nav three columns">
        
<ul>
<li><a href="#functions">Functions</a><ul>
<li><a href="#calling-functions">Calling Functions</a></li>
<li><a href="#implicit-returning">Implicit Returning</a></li>
<li><a href="#exercises">Exercises</a></li>
</ul>
</li>
</ul>


        <div class="prevnext">
            
                <a class="prev" href="22.html">&laquo; Prev</a>
            
            
                <a class="next" href="24.html">Next &raquo;</a>
            
        </div>
    </section>

    <section class="content twelve columns offset-by-one">
        <div> 
<h1 id="functions">Functions</h1>
<p>Like most programming languages, Vimscript has functions.  Let's take a look at
how to create them, and then talk about some of their quirks.</p>
<p>Run the following command:</p>
<pre class="codehilite"><code class="language-vim">:function meow()</code></pre>


<p>You might think this would start defining a function named <code>meow</code>.
Unfortunately this is not the case, and we've already run into one of
Vimscript's quirks.</p>
<p><strong>Vimscript functions <em>must</em> start with a capital letter if they are unscoped!</strong></p>
<p>Even if you <em>do</em> add a scope to a function (we'll talk about that later) you
may as well capitalize the first letter of function names anyway.  Most
Vimscript coders seem to do it, so don't break the convention.</p>
<p>Okay, let's define a function for real this time.  Run the following commands:</p>
<pre class="codehilite"><code class="language-vim">:function Meow()
:  echom "Meow!"
:endfunction</code></pre>


<p>This time Vim will happily define the function.  Let's try running it:</p>
<pre class="codehilite"><code class="language-vim">:call Meow()</code></pre>


<p>Vim will display <code>Meow!</code> as expected.</p>
<p>Let's try returning a value.  Run the following commands:</p>
<pre class="codehilite"><code class="language-vim">:function GetMeow()
:  return "Meow String!"
:endfunction</code></pre>


<p>Now try it out by running this command:</p>
<pre class="codehilite"><code class="language-vim">:echom GetMeow()</code></pre>


<p>Vim will call the function and give the result to <code>echom</code>, which will display
<code>Meow String!</code>.</p>
<h2 id="calling-functions">Calling Functions</h2>
<p>We can already see that there are two different ways of calling functions in
Vimscript.</p>
<p>When you want to call a function directly you use the <code>call</code> command.  Run the
following commands:</p>
<pre class="codehilite"><code class="language-vim">:call Meow()
:call GetMeow()</code></pre>


<p>The first will display <code>Meow!</code> but the second doesn't display anything. The
return value is thrown away when you use <code>call</code>, so this is only useful when the
function has side effects.</p>
<p>The second way to call functions is in expressions.  You don't need to use
<code>call</code> in this case, you can just name the function.  Run the following command:</p>
<pre class="codehilite"><code class="language-vim">:echom GetMeow()</code></pre>


<p>As we saw before, this calls <code>GetMeow</code> and passes the return value to <code>echom</code>.</p>
<h2 id="implicit-returning">Implicit Returning</h2>
<p>Run the following command:</p>
<pre class="codehilite"><code class="language-vim">:echom Meow()</code></pre>


<p>This will display two lines: <code>Meow!</code> and <code>0</code>.  The first obviously comes from
the <code>echom</code> inside of <code>Meow</code>.  The second shows us that if a Vimscript function
doesn't return a value, it implicitly returns <code>0</code>.  Let's use this to our
advantage.  Run the following commands:</p>
<pre class="codehilite"><code class="language-vim">:function TextwidthIsTooWide()
:  if &amp;l:textwidth &gt;# 80
:    return 1
:  endif
:endfunction</code></pre>


<p>This function uses a lot of important concepts we've seen before:</p>
<ul>
<li><code>if</code> statements</li>
<li>Treating options as variables</li>
<li>Localizing those option variables</li>
<li>Case-sensitive comparisons</li>
</ul>
<p>If any of those sound unfamiliar you should go back a few chapters and read
about them.</p>
<p>We've now defined a function that will tell us if the <code>textwidth</code> setting is
"too wide" in the current buffer (because 80 characters is, of course, the
correct width for anything but HTML).</p>
<p>Let's try using it.  Run the following commands:</p>
<pre class="codehilite"><code class="language-vim">:set textwidth=80
:if TextwidthIsTooWide()
:  echom "WARNING: Wide text!"
:endif</code></pre>


<p>What did we do here?</p>
<ul>
<li>First we set the <code>textwidth</code> globally to <code>80</code>.</li>
<li>Then we ran an if statement that checked if <code>TextwidthIsTooWide()</code> was truthy.</li>
<li>This wound up not being the case, so the <code>if</code>'s body wasn't executed.</li>
</ul>
<p>Because we never explicitly returned a value, Vim returned <code>0</code> from the
function, which is falsy.  Let's try changing that.  Run the following commands:</p>
<pre class="codehilite"><code class="language-vim">:setlocal textwidth=100
:if TextwidthIsTooWide()
:  echom "WARNING: Wide text!"
:endif</code></pre>


<p>This time the <code>if</code> statement in the function executes its body, returns <code>1</code>, and
so the <code>if</code> we manually typed in executes <em>its</em> body.</p>
<h2 id="exercises">Exercises</h2>
<p>Read <code>:help :call</code>.  Ignore anything about "ranges" for now.  How many arguments
can you pass to a function?  Is this surprising?</p>
<p>Read the first paragraph of <code>:help E124</code> and find out what characters you're
allowed to use in function names.  Are underscores okay?  Dashes?  Accented
characters?  Unicode characters?  If it's not clear from the documentation just
try them out and see.</p>
<p>Read <code>:help return</code>.  What's the "short form" of that command (which I told you
to never use)?  Is it what you expected?  If not, why not?</p></div>

        <div class="prevnext">
            
                <a class="prev" href="22.html">&laquo; Previous</a>
            
            
                <a class="next" href="24.html">Next &raquo;</a>
            
        </div>
    </section>


            <footer class="sixteen columns">
                Made by <a href="http://stevelosh.com">Steve Losh</a>.

                <a href="/license.html">License</a>.

                Built with
                <a href="http://bitbucket.org/sjl/bookmarkdown/">Bookmarkdown</a>.
            </footer>
        </div>

        
            <script type="text/javascript">
                var _gaq = _gaq || [];
                _gaq.push(['_setAccount', 'UA-15328874-8']);
                _gaq.push(['_trackPageview']);

                (function() {
                 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
                 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
                 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
                 })();
            </script>
        

        
            <script type="text/javascript">
                var _gauges = _gauges || [];
                (function() {
                 var t   = document.createElement('script');
                 t.type  = 'text/javascript';
                 t.async = true;
                 t.id    = 'gauges-tracker';
                 t.setAttribute('data-site-id', '4e8f83b7f5a1f546e200000d');
                 t.src = '//secure.gaug.es/track.js';
                 var s = document.getElementsByTagName('script')[0];
                 s.parentNode.insertBefore(t, s);
                 })();
             </script>
        
    </body>
</html>
